// i.d(t, {
//   I_: () => l,
//   Hq: () => c,
//   P6: () => h,
//   R5: () => d,
//   Tp: () => u,
//   Tu: () => p,
//   ym: () => m,
//   oU: () => g,
//   eO: () => v
// })

import cubeEnum from "../enum/cube.enum"
import * as THREE from "three"
import { getCubeFace } from "../utils/cube.util"
import a from "./7170"
import tileEnum from "../enum/tile.enum"

const l = 512,
  c = 6,
  h = (e, t, i, s, o, a, l, c) => {
    const h = e / t,
      d = 2 * (t / e),
      u = d / 2
    let p = 2 * (s / h) - 1 + u,
      m = 2 * ((o = h - 1 - o) / h) - 1 + u
    switch ((a = a || tileEnum.Center)) {
      case tileEnum.UpperLeft:
        ;(p -= u), (m += u), (p += l * d)
        break
      case tileEnum.UpperRight:
        ;(p += u), (m += u), (m -= l * d)
        break
      case tileEnum.LowerRight:
        ;(p += u), (m -= u), (p -= l * d)
        break
      case tileEnum.LowerLeft:
        ;(p -= u), (m -= u), (m += l * d)
        break
      case tileEnum.Center:
    }
    switch (i) {
      case cubeEnum.GL_TEXTURE_CUBE_MAP_POSITIVE_X:
        c.set(-1, m, -p)
        break
      case cubeEnum.GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
        c.set(1, m, p)
        break
      case cubeEnum.GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
        c.set(-p, 1, -m)
        break
      case cubeEnum.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
        c.set(-p, -1, m)
        break
      case cubeEnum.GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
        c.set(-p, m, 1)
        break
      case cubeEnum.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
        c.set(p, m, -1)
    }
    c.normalize()
  },
  d = (e, t) => {
    let i = l
    e < l && (i = e)
    const n = Math.floor(e / i),
      s = n * n
    return Math.floor(t / s)
  },
  u = (e, t, i) => {
    let n = l
    e < l && (n = e)
    const s = d(e, t),
      r = Math.floor(e / n),
      o = t - s * (r * r)
    ;(i.tileX = o % r), (i.tileY = Math.floor(o / r)), (i.face = s), (i.faceTileIndex = o)
  },
  p = function (e) {
    if (e <= l) return c
    const t = Math.floor(e / l)
    return t * t * c
  },
  m = (function () {
    const e = new THREE.Matrix4(),
      t = new THREE.Quaternion()
    return (i: THREE.Quaternion, n: THREE.Vector3) => {
      t.copy(i)
      t.invert()
      e.makeRotationFromQuaternion(t)
      n.applyMatrix4(e)
      n.normalize()
    }
  })(),
  g = (function () {
    const e = new THREE.Vector3(),
      t = new THREE.Vector3(0, 0, -1),
      i = new THREE.Quaternion(),
      n = function (e, t) {
        e.push({
          face: t.face,
          faceTileIndex: t.faceTileIndex,
          tileX: t.tileX,
          tileY: t.tileY
        })
      },
      r = (function () {
        const e = { face: -1, faceTileIndex: -1, tileX: -1, tileY: -1 }
        return (t, i, s) => {
          const r = p(t)
          let o = 0
          for (let a = 0; a < r; a++) u(t, a, e), (i && !i(e)) || (o++, s && n(s, e))
          return o
        }
      })()
    return (n, o, a, c, h = !1, d?, u?) => {
      c.length = h ? 0 : c.length
      const p = o < l ? o : l
      if (!d && !u) return r(o, null, c)
      const g = !!u
      ;(d = d || 0), (u = u || d), (u = Math.max(0, Math.min(u, 360))), (d = Math.max(0, Math.min(d, 360))), e.copy(a)
      const y = n.rotation || new THREE.Quaternion()
      if ((m(y, e), g)) {
        i.setFromUnitVectors(e, t)
        return r(
          o,
          function (e) {
            return f(o, p, e.face, e.tileX, e.tileY, i, d || 0, u || 0)
          },
          c
        )
      }
      return r(
        o,
        function (t) {
          return v(o, p, t.face, t.tileX, t.tileY, e, d || 0)
        },
        c
      )
    }
  })(),
  f = (function () {
    const e = new THREE.Vector3()
    return (t, i, n, s, l, c, d, u) => {
      const p = Math.tan(0.5 * u * a.Ue),
        m = -p,
        g = Math.tan(0.5 * d * a.Ue),
        f = -g,
        v = getCubeFace(n)
      let y = 0,
        b = 0,
        S = 0,
        E = 0,
        T = 0
      for (let n = tileEnum.Center; n <= tileEnum.LowerLeft; n++) {
        if ((h(t, i, v, s, l, n, 0, e), e.applyQuaternion(c), e.z >= -1e-5)) continue
        const r = -1 / e.z,
          o = e.x * r,
          a = e.y * r
        a > p ? y++ : a < m && b++, o > g ? S++ : o < f && E++, T++
      }
      return b !== T && y !== T && S !== T && E !== T
    }
  })(),
  v = (function () {
    const e = new THREE.Vector3(),
      t = new THREE.Vector3(0, 1, 0),
      i = new THREE.Vector3(1, 0, 0)
    return (n, s, a, l, c, d, u) => {
      const p = getCubeFace(a)
      if ((i.copy(d).cross(t), h(n, s, p, l, c, tileEnum.Center, 0, e), y(e, d, u))) return !0
      const m = u / 360,
        g = Math.floor(1 / m)
      let f = 0
      for (let t = 0; t < g; t++) {
        for (let t = tileEnum.UpperLeft; t <= tileEnum.LowerLeft; t++) if ((h(n, s, p, l, c, t, f, e), y(e, d, u))) return !0
        f += m
      }
      return !1
    }
  })(),
  y = (function () {
    const e = new THREE.Vector3(),
      t = new THREE.Vector3()
    return (i, n, s, r?) => {
      if ((t.copy(i), r)) {
        e.copy(r), e.normalize()
        const n = e.dot(i)
        ;(e.x *= n), (e.y *= n), (e.z *= n), t.sub(e)
      }
      const o = (s / 2) * a.Ue,
        l = Math.cos(o)
      return t.dot(n) >= l
    }
  })()
export default {
  I_: l,
  Hq: c,
  P6: h,
  R5: d,
  Tp: u,
  Tu: p,
  ym: m,
  oU: g,
  eO: v
}
